package com.googlecode.openrtp.grizzly.rtcp.filter;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction;
import com.googlecode.openrtp.grizzly.util.BufferUtil;
import com.googlecode.openrtp.spi.rtcp.RtcpHeaderPacket;
import com.googlecode.openrtp.spi.rtcp.RtcpSenderPacket;

/**
 *
 * @author jocke
 */
public class RtcpSenderReportFilter extends BaseFilter {

    private final BufferUtil bufferUtil;
    private static final Logger LOG = Logger.getLogger(RtcpSenderReportFilter.class.getName());

    @Inject
    public RtcpSenderReportFilter(BufferUtil bufferUtil) {
        this.bufferUtil = bufferUtil;
    }

    @Override
    public NextAction handleRead(FilterChainContext ctx) throws IOException {

        Buffer sourceBuffer = ctx.getMessage();
        
        RtcpHeaderPacket headerPacket = (RtcpHeaderPacket) ctx.getAttributes().getAttribute(RtcpHeaderPacket.class.getName());

        ByteBuffer longBuffer = bufferUtil.allocate(ctx, 8);
        ByteBuffer intBuffer = bufferUtil.allocate(ctx, 4);

        long ssrc = bufferUtil.getUnsignedIntAsLong(sourceBuffer, longBuffer);
        long ntp = sourceBuffer.getLong();
        int rtpTimestamp = sourceBuffer.getInt();
        int senderPacketCount = sourceBuffer.getInt();
        int senderOctetCount = sourceBuffer.getInt();

        Map<Long, RtcpSenderPacket.ReceiverReportBlock> blocks;

        if (headerPacket.getRc() > 0) {
            
            blocks = new HashMap<>(headerPacket.getRc());
            
            for (int i = 0; i < headerPacket.getRc(); i++) {
                long ssrcn = bufferUtil.getUnsignedIntAsLong(sourceBuffer, longBuffer);
                int fractionLost = sourceBuffer.get();
                int cumulativePacketLost = sourceBuffer.get(intBuffer, 1, 3).getInt();
                int highestSequenceNumber = sourceBuffer.getInt();
                int interarrivalJitter = sourceBuffer.getInt();
                int lsr = sourceBuffer.getInt();
                int dlsr = sourceBuffer.getInt();
                blocks.put(ssrc, RtcpSenderPacket.ReceiverReportBlock.create(
                        ssrcn,
                        fractionLost,
                        cumulativePacketLost,
                        highestSequenceNumber,
                        interarrivalJitter,
                        lsr,
                        dlsr));
            }
            
        } else {
            blocks = Collections.emptyMap();
        }

        RtcpSenderPacket packet = RtcpSenderPacket.create(
                headerPacket,
                ssrc,
                ntp,
                rtpTimestamp,
                senderPacketCount,
                senderOctetCount,
                blocks);

        bufferUtil.release(ctx, longBuffer);
        bufferUtil.release(ctx, intBuffer);
        
        ctx.setMessage(packet);
        
        LOG.log(Level.INFO, "RTCP Sender packet has arrived {0}", packet);

        return super.handleRead(ctx);
    }
}
